package com.zzw.bridge.business.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zzw.bridge.business.dto.AddProjectDTO;
import com.zzw.bridge.business.dto.ZzwPierProjectDTO;
import com.zzw.bridge.business.vo.QueryIdVo;
import com.zzw.bridge.business.vo.ZzwPierProjectVo;
import com.zzw.bridge.common.entitys.business.ZzwPierProjectEntity;
import com.zzw.bridge.common.enums.AddTypeEnum;
import com.zzw.bridge.common.enums.ProjectTypeEnum;
import com.zzw.bridge.common.exception.ServerException;
import com.zzw.bridge.common.utils.TreeBuilderUtils;
import com.zzw.bridge.security.cache.TokenStoreCache;
import org.springframework.stereotype.Service;
import com.zzw.bridge.business.dao.ZzwPierProjectDao;
import com.zzw.bridge.business.service.ZzwPierProjectService;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.stream.Collectors;


@Service
public class ZzwPierProjectServiceImpl extends ServiceImpl<ZzwPierProjectDao, ZzwPierProjectEntity> implements ZzwPierProjectService {

    @Resource
    private TokenStoreCache tokenStoreCache;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String addProject(AddProjectDTO dto, HttpServletRequest request) {
        dto.setAccountUsername(tokenStoreCache.getCurrentUser(request).getUsername());
        int count = 0;
        //新增父级
        if (ObjectUtil.isNotNull(dto)&& AddTypeEnum.ADD_TYPE_PARENT.getValue().equals(dto.getAddType())) {
            if (ObjectUtil.isNull(dto.getCurrentId())) {
               throw new ServerException("创建父级时当前id不能为空！！");
            }
            String id = UUID.randomUUID().toString().replace("-", "");
            ZzwPierProjectEntity entity = new ZzwPierProjectEntity();
            BeanUtil.copyProperties(dto,entity);
            entity.setProjectStatus(1);
            entity.setIsDelete(0);
            entity.setId(id);
            entity.setCreateTime(new Date());
            entity.setUpdateTime(new Date());
            count=baseMapper.insert(entity);
            String currentId = dto.getCurrentId();
            LambdaUpdateWrapper<ZzwPierProjectEntity> updateWrapper = Wrappers.lambdaUpdate(ZzwPierProjectEntity.class)
                    .eq(ZzwPierProjectEntity::getId, currentId)
                    .set(ZzwPierProjectEntity::getParentId, id);
            baseMapper.update(new ZzwPierProjectEntity(),updateWrapper);
        }
        //新增同级
        if (ObjectUtil.isNotNull(dto)&& AddTypeEnum.ADD_TYPE_VIS_A_VIS.getValue().equals(dto.getAddType())) {
            count=baseMapper.insertProject(dto);
        }
        //新增子级
        if (ObjectUtil.isNotNull(dto)&& AddTypeEnum.ADD_TYPE_SON.getValue().equals(dto.getAddType())) {
            String id = UUID.randomUUID().toString().replace("-", "");
            ZzwPierProjectEntity entity = new ZzwPierProjectEntity();
            BeanUtil.copyProperties(dto,entity);
            entity.setId(id);
            entity.setProjectStatus(1);
            entity.setIsDelete(0);
            entity.setParentId(dto.getCurrentId());
            entity.setCreateTime(new Date());
            entity.setUpdateTime(new Date());
            count=baseMapper.insert(entity);
        }
        //初始化项目
        if (ObjectUtil.isNotNull(dto)&& AddTypeEnum.INITIALIZATION_PROJECT.getValue().equals(dto.getAddType())) {
            count=baseMapper.insertProject(dto);
        }
        return String.format("成功新增%s条项目",count);
    }

    @Override
    public List<ZzwPierProjectVo> queryPage(ZzwPierProjectDTO dto, HttpServletRequest request) {
        String username = tokenStoreCache.getCurrentUser(request).getUsername();
        dto.setAccountUsername(username);
        List<ZzwPierProjectVo> zzwPierProjectVos = baseMapper.selectListByUsername(username);
        List<ZzwPierProjectVo> tree = TreeBuilderUtils.tree(zzwPierProjectVos, ZzwPierProjectVo::getParentId, ZzwPierProjectVo::getId, ZzwPierProjectVo::setSubsetList);
        return tree.stream().sorted(Comparator.comparing(ZzwPierProjectVo::getCreateTime)).collect(Collectors.toList());
    }

    @Override
    public Integer removeProject(String id) {
        LambdaUpdateWrapper<ZzwPierProjectEntity> updateWrapper = Wrappers.lambdaUpdate(ZzwPierProjectEntity.class).eq(ZzwPierProjectEntity::getId, id).set(ZzwPierProjectEntity::getIsDelete, 1);
        return baseMapper.update(new ZzwPierProjectEntity(),updateWrapper);
    }

    @Override
    public Integer editProject(ZzwPierProjectDTO dto) {
        return baseMapper.updateByDto(dto);
    }

    @Override
    public Boolean checkEndLevel(String id,HttpServletRequest request) {
        ZzwPierProjectDTO dto = new ZzwPierProjectDTO();
        List<ZzwPierProjectVo> list = this.queryPage(dto, request);
        ZzwPierProjectVo voById = findVoById(list, id);
        Integer voEndLevel = getVoEndLevel(voById);
        System.out.println("末端节点------------------="+voEndLevel);
        return voEndLevel < 4;
    }

    @Override
    public HashMap<Integer, String> queryProjectType() {
        ProjectTypeEnum[] values = ProjectTypeEnum.values();
        HashMap<Integer, String> hashMap = new HashMap<>();
        Arrays.stream(values).forEach(value->{
            hashMap.put(value.getLevel(),value.getName());
        });
        return hashMap;
    }

    @Override
    public List<QueryIdVo> queryIdList(Integer projectType) {
        return baseMapper.selectIdList(projectType);
    }

    @Override
    public Map<Integer, List<ZzwPierProjectVo>> queryTypeList(HttpServletRequest request) {
        String username = tokenStoreCache.getCurrentUser(request).getUsername();
        List<ZzwPierProjectVo> list = baseMapper.selectListByUsername(username);
        return list.stream().collect(Collectors.groupingBy(ZzwPierProjectVo::getProjectType));
    }

    @Override
    public ZzwPierProjectVo queryVoById(HttpServletRequest request, String id) {
        List<ZzwPierProjectVo> list = this.queryPage(new ZzwPierProjectDTO(), request);

        return findVoById(list,id);
    }

    /**
     * 递归设置层级关系
     * @param vo "条件"
     */
    private void setLevel(ZzwPierProjectVo vo,Integer level){
        if (ObjectUtil.isNotNull(vo)) {
            vo.setLevel(level);
            if (ObjectUtil.isNotNull(vo.getSubsetList())) {
                level++;
                for (ZzwPierProjectVo zzwPierProjectVo : vo.getSubsetList()) {
                    setLevel(zzwPierProjectVo,level);
                }
            }
        }
    }

    /**
     * 根据id查找树形结构中的vo
     * @param treeList "树形结构list"
     * @param targetId "目标id"
     * @return {@link ZzwPierProjectVo}
     */
    public ZzwPierProjectVo findVoById(List<ZzwPierProjectVo> treeList, String targetId) {
        if (ObjectUtil.isNull(treeList)) {
            return null;
        }
        for (ZzwPierProjectVo vo : treeList) {
            if (vo.getId().equals(targetId)) {
                return vo;
            }
            ZzwPierProjectVo found = findVoById(vo.getSubsetList(), targetId);
            if (found != null) {
                return found;
            }
        }
        return null;
    }

    /**
     * 查找目标vo的末节点层级
     * @param vo {@link ZzwPierProjectVo}
     * @return {@link Integer}
     */
//    public Integer getVoEndLevel(ZzwPierProjectVo vo) {
//        if (ObjectUtil.isNull(vo)) {
//            return 0;
//        }
//        if (ObjectUtil.isNull(vo.getSubsetList())) {
//            return vo.getLevel();
//        }
//        for (ZzwPierProjectVo zzwPierProjectVo : vo.getSubsetList()) {
//            if (zzwPierProjectVo.getIsEndNode().equals(1)) {
//                return zzwPierProjectVo.getLevel();
//            }
//            Integer voEndLevel = getVoEndLevel(zzwPierProjectVo);
//            if (voEndLevel != null) {
//                return voEndLevel;
//            }
//        }
//       return 0;
//    }

    /**
     * 查看目标vo下子级最深的level
     *
     * @param vo {@link ZzwPierProjectVo}
     * @return {@link Integer}
     */
    public Integer getVoEndLevel(ZzwPierProjectVo vo) {
        // 当前节点为空，返回 0
        if (ObjectUtil.isNull(vo)) {
            return 0;
        }
        // 当前节点没有子节点，返回当前节点的层级
        if (ObjectUtil.isNull(vo.getSubsetList())) {
            return vo.getLevel();
        }
        int maxEndLevel = 0;
        // 遍历子节点
        for (ZzwPierProjectVo childVo : vo.getSubsetList()) {
            // 递归计算子节点的最深层级
            int childEndLevel = getVoEndLevel(childVo);
            // 更新最大层级
            maxEndLevel = Math.max(maxEndLevel, childEndLevel);
        }
        return maxEndLevel;
    }
}
